﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ASC.DB;
using ASC.Models;
using ASC.Attributes;

namespace ASC.Controllers
{
    public class ChannelController : BaseController
    {

        public ActionResult Index(int id)
        {
            var channel = this.db.Channels.FirstOrDefault(x => x.Channel_Id == id);
            if (channel == null)
                Response.Redirect("~/");

            var availableChannels = this.db.Channels.Where(x => x.ChannelType.BaseType == channel.ChannelType.BaseType && x.Channel_Id != id).ToList();
            var plusChannels = (from bch in this.db.Base_Ch
                               join ch in this.db.Channels on bch.Base_Ch1 equals ch.Channel_Id
                               where bch.Channel == id && bch.Neg == false
                               select ch).ToList();
            var minusChannels = (from bch in this.db.Base_Ch
                                 join ch in this.db.Channels on bch.Base_Ch1 equals ch.Channel_Id
                                 where bch.Channel == id && bch.Neg == true
                                 select ch).ToList();


            var channelModel = new ChannelModel()
            {

                Channel = channel,
                AvailableChannels = availableChannels.Except(plusChannels).ToList().Except(minusChannels).ToList(),
                PlusChannels = plusChannels,
                MinusChannels = minusChannels

            };

            return View(channelModel);
        }

        #region Edit
        public ActionResult Edit(int? id)
        {

            var channel = this.db.Channels.FirstOrDefault(x => x.Channel_Id == id);
            if (channel != null)
            {
                var avaribleChannels = this.db.Channels.Where(x => x.ChannelType.BaseType == channel.ChannelType.BaseType && x.Channel_Id != id).ToList();
                var plusChannels = (from ch in this.db.Channels
                                    join bch in this.db.Base_Ch on ch.Channel_Id equals bch.Base_Ch1
                                    where bch.Neg == false && bch.Channel == id
                                    select ch).ToList();
                var minusChannels = (from ch in this.db.Channels
                                     join bch in this.db.Base_Ch on ch.Channel_Id equals bch.Base_Ch1
                                     where bch.Neg == true && bch.Channel == id
                                    select ch).ToList();

                var channelModel = new ChannelModel()
                {
                    ChannelAddress = channel.ChannelAddress,
                    Channel = channel,
                    ChannelTypes = this.db.ChannelTypes.ToList(),
                    AvailableChannels = avaribleChannels.Except(plusChannels).Except(minusChannels).ToList(),
                    PlusChannels = plusChannels,
                    MinusChannels = minusChannels
                };

                return View(channelModel);
            }
            else
                return View();
        }

        [HttpPost]
        [SubmitButton] 
        public ActionResult Edit(ChannelModel model, string plusMinus, string[] PlusChannels, string[] MinusChannels)
        {
            if (!string.IsNullOrEmpty(model.Channel.Name))
            {
                var channel = this.db.Channels.FirstOrDefault(x => x.Channel_Id == model.Channel.Channel_Id);
                channel.Name = model.Channel.Name;
                channel.Description = model.Channel.Description;
                channel.ChannelType_Id = model.Channel.ChannelType_Id;
                channel.Transtype = model.Channel.Transtype;
                channel.Used = model.Channel.Used;
                channel.Sign = model.Channel.Sign;
                channel.SaveStat = model.Channel.SaveStat;
                channel.OrdNr = model.Channel.OrdNr;
                channel.Operation = model.Channel.Operation;
                channel.Offset = model.Channel.Offset;
                channel.Interval1 = model.Channel.Interval1;
                channel.Interval = model.Channel.Interval;
                channel.Factor = model.Channel.Factor;

                var channelAddress = channel.ChannelAddress;
                channelAddress.AddressBit = model.ChannelAddress.AddressBit;
                channelAddress.AddressByte = model.ChannelAddress.AddressByte;
                channelAddress.AsyncType = model.ChannelAddress.AsyncType;
                channelAddress.Drive = model.ChannelAddress.Drive;
                channelAddress.Hi = model.ChannelAddress.Hi;
                channelAddress.Inverted = model.ChannelAddress.Inverted;
                channelAddress.Low = model.ChannelAddress.Low;
                channelAddress.On_Error = model.ChannelAddress.On_Error;
                channelAddress.Port = model.ChannelAddress.Port;
                channelAddress.Subunit = model.ChannelAddress.Subunit;
                channelAddress.Unit = model.ChannelAddress.Unit;
                channelAddress.WordLength = model.ChannelAddress.WordLength;

                var channelType = db.ChannelTypes.First(x => x.ChannelType_Id == model.Channel.ChannelType_Id);

                switch (channelType.BaseType)
                {
                    case 1:
                        {
                            channel.Sign = false;
                            channel.Interval = null;
                            channelAddress.AddressBit = null;
                            channelAddress.Inverted = false;
                        } break;
                    case 2:
                        {
                            channel.Transtype = null;
                            channel.Interval = null;
                            channel.Offset = null;
                            channelAddress.WordLength = null;
                        } break;
                    case 3:
                        {
                            if (plusMinus == "high")
                                channel.Operation = 0;
                            else if (plusMinus == "low")
                                channel.Operation = 1;


                            channel.Sign = false;
                            channel.Transtype = null;
                            channel.Interval = null;
                            channel.Offset = null;
                            channelAddress = new ChannelAddress() { AsyncType = model.ChannelAddress.AsyncType };

                        } break;
                    case 4:
                        {
                            channel.Sign = false;
                            channel.Transtype = null;
                            channel.Interval = null;
                            channel.Offset = null;
                            channelAddress.WordLength = null;
                            channelAddress.AddressBit = null;

                        } break;
                    case 5:
                        {
                            channel.Sign = false;
                            channel.Transtype = null;
                            channel.Interval = null;
                            channel.Offset = null;

                        } break;
                    case 20:
                        {
                            if (plusMinus == "high")
                                channel.Operation = 5;
                            else if (plusMinus == "low")
                                channel.Operation = 4;
                            channel.Sign = false;
                            channel.Transtype = null;
                            channel.Interval = null;
                            channel.Offset = null;
                            channelAddress = new ChannelAddress() { Inverted = model.ChannelAddress.Inverted, AsyncType = model.ChannelAddress.AsyncType };

                        } break;
                }

                this.db.ExecuteStoreCommand("delete Base_Ch where Channel={0}", channel.Channel_Id);
                db.SaveChanges();

                if (PlusChannels != null)
                {
                    foreach (string m in PlusChannels)
                    {
                        db.Base_Ch.AddObject(new Base_Ch
                        {
                            Channel = model.Channel.Channel_Id,
                            Base_Ch1 = int.Parse(m),
                            Neg = false
                        });
                    }
                }


                if (MinusChannels != null)
                {
                    foreach (string m in MinusChannels)
                    {
                        db.Base_Ch.AddObject(new Base_Ch
                        {
                            Channel = model.Channel.Channel_Id,
                            Base_Ch1 = int.Parse(m),
                            Neg = true
                        });
                    }
                }

                db.SaveChanges();


            }
            return RedirectToAction("Edit", new { Id = model.Channel.Channel_Id });
        }
        #endregion

        #region SaveAsNew

        [HttpPost]
        [SubmitButton] 
        public ActionResult SaveAsNew(ChannelModel model, string plusMinus, string[] PlusChannels, string[] MinusChannels)
        {
            return Add(model, plusMinus, PlusChannels, MinusChannels);
        }

        #endregion

        #region Create
        public ActionResult Add(int? moduleType_Id)
        {

            var channelModel = new ChannelModel()
            {
                ChannelAddress = new ChannelAddress(),
                Channel = new DB.Channel(),
                ChannelTypes = moduleType_Id == null ?
                this.db.ChannelTypes.ToList()
                :(from mt in this.db.ModuleType_ChannelType
                               join cht in this.db.ChannelTypes on mt.ChannelType_Id equals cht.ChannelType_Id
                                where (mt.ModuleType_Id == moduleType_Id)
                                select cht)
                                .Distinct()
                                .ToList(),
                AvailableChannels = new List<Channel>(),//this.db.Channels.Where(x => x.ChannelType.BaseType == 1),
                PlusChannels = new List<Channel>(),
                MinusChannels = new List<Channel>()
            };

            return View(channelModel);
        }

        [HttpPost]
        public ActionResult Add(ChannelModel model, string plusMinus, string[] PlusChannels, string[] MinusChannels)
        {
            if (!string.IsNullOrEmpty(model.Channel.Name))
            {

                var channelType = db.ChannelTypes.First(x => x.ChannelType_Id == model.Channel.ChannelType_Id);
                switch (channelType.BaseType)
                {
                    case 1:
                        {
                            model.Channel.Sign = false;
                            model.Channel.Interval = null;
                            model.ChannelAddress.AddressBit = null;
                            model.ChannelAddress.Inverted = false;
                        } break;
                    case 2:
                        {
                            model.Channel.Transtype = null;
                            model.Channel.Interval = null;
                            model.Channel.Offset = null;
                            model.ChannelAddress.WordLength = null;
                        } break;
                    case 3:
                        {
                            if (plusMinus == "high")
                                model.Channel.Operation = 0;
                            else if (plusMinus == "low")
                                model.Channel.Operation = 1;

                            model.Channel.Sign = false;
                            model.Channel.Transtype = null;
                            model.Channel.Interval = null;
                            model.Channel.Offset = null;
                            model.ChannelAddress = new ChannelAddress() { AsyncType = model.ChannelAddress.AsyncType };

                        } break;
                    case 4:
                        {
                            model.Channel.Sign = false;
                            model.Channel.Transtype = null;
                            model.Channel.Interval = null;
                            model.Channel.Offset = null;
                            model.ChannelAddress.WordLength = null;
                            model.ChannelAddress.AddressBit = null;

                        } break;
                    case 5:
                        {
                            model.Channel.Sign = false;
                            model.Channel.Transtype = null;
                            model.Channel.Interval = null;
                            model.Channel.Offset = null;

                        } break;
                    case 20:
                        {
                            if (plusMinus == "high")
                                model.Channel.Operation = 5;
                            else if(plusMinus == "low")
                                model.Channel.Operation = 4;

                            model.Channel.Sign = false;
                            model.Channel.Transtype = null;
                            model.Channel.Interval = null;
                            model.Channel.Offset = null;
                            model.ChannelAddress = new ChannelAddress() { Inverted = model.ChannelAddress.Inverted, AsyncType = model.ChannelAddress.AsyncType };

                        } break;
                }

                db.ChannelAddresses.AddObject(model.ChannelAddress);
                db.SaveChanges();

                model.Channel.ChannelAddress_Id = model.ChannelAddress.ChannelAddress_Id;

                db.Channels.AddObject(model.Channel);
                db.SaveChanges();

                if (PlusChannels != null)
                {
                    foreach (string m in PlusChannels)
                    {
                        db.Base_Ch.AddObject(new Base_Ch
                        {
                            Channel = model.Channel.Channel_Id,
                            Base_Ch1 = int.Parse(m),
                            Neg = false
                        });
                    }
                }


                if (MinusChannels != null)
                {
                    foreach (string m in MinusChannels)
                    {
                        db.Base_Ch.AddObject(new Base_Ch
                        {
                            Channel = model.Channel.Channel_Id,
                            Base_Ch1 = int.Parse(m),
                            Neg = true
                        });
                    }
                }

                db.SaveChanges();

                return RedirectToAction("Edit", new { Id = model.Channel.Channel_Id });
            }
            else
            {
                return View(model);
            }
 
        }
        #endregion

        [HttpPost]
        public JsonResult GetBaseChannels(int baseTypeId, int? channel_id)
        {
            if (baseTypeId == 3)
                baseTypeId = 1;
            else if (baseTypeId == 20)
                baseTypeId = 2;
            else
                return new JsonResult();

            var avaribleChannels = (from ch in this.db.Channels
                                   join cht in this.db.ChannelTypes on ch.ChannelType_Id equals cht.ChannelType_Id
                                   where cht.BaseType == baseTypeId && ch.Channel_Id != channel_id
                                   select new { Name = ch.Name, ID = ch.Channel_Id })
                                    .ToList();

            var plusChannels = (from ch in this.db.Channels
                                join bch in this.db.Base_Ch on ch.Channel_Id equals bch.Base_Ch1
                                where bch.Neg == false && bch.Channel == channel_id
                                select new { Name = ch.Name, ID = ch.Channel_Id }).ToList();
            var minusChannels = (from ch in this.db.Channels
                                 join bch in this.db.Base_Ch on ch.Channel_Id equals bch.Base_Ch1
                                 where bch.Neg == true && bch.Channel == channel_id
                                 select new { Name = ch.Name, ID = ch.Channel_Id }).ToList();

            return Json(new { AvaribleChannels = avaribleChannels.Except(plusChannels).Except(minusChannels) });
        }

        [HttpPost]
        [SubmitButton]  
        public ActionResult Delete(int id)
        {
            var channel = this.db.Channels.FirstOrDefault(x => x.Channel_Id == id);

            this.db.DeleteObject(channel.ChannelAddress);
            this.db.DeleteObject(channel);
            this.db.ExecuteStoreCommand("delete Base_Ch where Channel={0}", channel.Channel_Id);
            this.db.ExecuteStoreCommand("delete Module_Channel where Channel_Id={0}", channel.Channel_Id);
            this.db.SaveChanges();

            return RedirectToAction("Index", "Home");
        }
    }
}
